package ar.com.miguelgriffa.secureproperties.ui.swing;

import java.awt.BorderLayout;
import java.awt.HeadlessException;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.Map;

import javax.swing.DefaultCellEditor;
import javax.swing.JDialog;
import javax.swing.JFileChooser;
import javax.swing.JLabel;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.JTextField;
import javax.swing.KeyStroke;
import javax.swing.WindowConstants;
import javax.swing.table.DefaultTableModel;

import ar.com.miguelgriffa.secureproperties.SecureProperties;


public class SecurePropertiesDialog extends JDialog {

	private static final long serialVersionUID = 1L;

	private JPanel jContentPane = null;

	private JScrollPane jScrollPane = null;

	private JTable jTable = null;

	private JMenuBar jJMenuBar = null;

	private JMenu jMenu = null;

	private JMenuItem openMenuItem = null;

	private JMenuItem delKeyMenuItem = null;

	private JMenuItem saveMenuItem = null;
	
	private JMenuItem saveAsMenuItem = null;

	private JMenuItem exitMenuItem = null;

	private JLabel statusBar;

	private DefaultTableModel dataModel = new DefaultTableModel();

	private File currentFile = null;

	private JMenuItem newKeyMenuItem;
	
	public SecurePropertiesDialog() throws HeadlessException {
		super();
		setModal(true);
		initialize();
	}


	/**
	 * This method initializes jScrollPane	
	 * 	
	 * @return javax.swing.JScrollPane	
	 */
	private JScrollPane getJScrollPane() {
		if (jScrollPane == null) {
			jScrollPane = new JScrollPane();
			jScrollPane.setViewportView(getJTable());
		}
		return jScrollPane;
	}

	/**
	 * This method initializes jTable	
	 * 	
	 * @return javax.swing.JTable	
	 */
	private JTable getJTable() {
		if (jTable == null) {
			jTable = new JTable();
			dataModel.setColumnCount(2);
			dataModel.setColumnIdentifiers(new String[]{"Key", "Value"});
			jTable.setModel(this.dataModel);
			jTable.setCellEditor(new DefaultCellEditor(new JTextField()));
		}
		return jTable;
	}

	/**
	 * This method initializes jJMenuBar	
	 * 	
	 * @return javax.swing.JMenuBar	
	 */
	private JMenuBar getJJMenuBar() {
		if (jJMenuBar == null) {
			jJMenuBar = new JMenuBar();
			jJMenuBar.add(getJMenu());
		}
		return jJMenuBar;
	}

	/**
	 * This method initializes jMenu	
	 * 	
	 * @return javax.swing.JMenu	
	 */
	private JMenu getJMenu() {
		if (jMenu == null) {
			jMenu = new JMenu();
			jMenu.setText("File");
			jMenu.add(getNewKeyMenuItem());
			jMenu.add(getOpenMenuItem());
			jMenu.add(getDelKeyMenuItem());
			jMenu.add(getSaveMenuItem());
			jMenu.add(getSaveAsMenuItem());
			jMenu.add(getExitMenuItem());
			jMenu.setMnemonic(KeyEvent.VK_F);
		}
		return jMenu;
	}


	private JMenuItem getNewKeyMenuItem() {
		if (newKeyMenuItem == null) {
			newKeyMenuItem = new JMenuItem();
			newKeyMenuItem.setAccelerator(KeyStroke.getKeyStroke('+'));
			newKeyMenuItem.setText("New Key");
			newKeyMenuItem.setMnemonic(KeyEvent.VK_K);
			newKeyMenuItem.addActionListener(new ActionListener(){
				public void actionPerformed(ActionEvent e) {
					addNewRow();
				}});
		}
		return newKeyMenuItem;
	}



	/**
	 * This method initializes openMenuItem	
	 * 	
	 * @return javax.swing.JMenuItem	
	 */
	private JMenuItem getOpenMenuItem() {
		if (openMenuItem == null) {
			openMenuItem = new JMenuItem();
			openMenuItem.setAccelerator(KeyStroke.getKeyStroke('o'));
			openMenuItem.setText("Open");
			openMenuItem.setMnemonic(KeyEvent.VK_O);
			openMenuItem.addActionListener(new ActionListener(){
				public void actionPerformed(ActionEvent e) {
					open();
				}});
		}
		return openMenuItem;
	}
	private JMenuItem getDelKeyMenuItem() {
		if (delKeyMenuItem == null) {
			delKeyMenuItem = new JMenuItem();
//			delKeyMenuItem.setAccelerator(KeyStroke.getKeyStroke('-'));
			delKeyMenuItem.setText("Delete key");
//			delKeyMenuItem.setMnemonic(KeyEvent.VK_E);
			delKeyMenuItem.addActionListener(new ActionListener(){
				public void actionPerformed(ActionEvent e) {
					delKey();
				}});
		}
		return delKeyMenuItem;
	}

	private void delKey() {
		int r = this.jTable.getSelectedRow();
		if (r<0) {
			JOptionPane.showMessageDialog(this, "Please select a row first");
		} else {
			System.out.println("r: "+r);
			this.jTable.removeRowSelectionInterval(r, r);
			dataModel.removeRow(r);
			dataModel.fireTableRowsDeleted(r, r);
		}
	}


	/**
	 * This method initializes saveMenuItem	
	 * 	
	 * @return javax.swing.JMenuItem	
	 */
	private JMenuItem getSaveMenuItem() {
		if (saveMenuItem == null) {
			saveMenuItem = new JMenuItem();
			saveMenuItem.setText("Save");
			saveMenuItem.setAccelerator(KeyStroke.getKeyStroke('s'));
			saveMenuItem.setMnemonic(KeyEvent.VK_S);
			saveMenuItem.addActionListener(new ActionListener(){
				public void actionPerformed(ActionEvent e) {
					save();
				}});
		}
		return saveMenuItem;
	}

	/**
	 * This method initializes saveMenuItem	
	 * 	
	 * @return javax.swing.JMenuItem	
	 */
	private JMenuItem getSaveAsMenuItem() {
		if (saveAsMenuItem == null) {
			saveAsMenuItem = new JMenuItem();
			saveAsMenuItem.setText("Save as");
			saveAsMenuItem.setMnemonic(KeyEvent.VK_A);
			saveAsMenuItem.addActionListener(new ActionListener(){
				public void actionPerformed(ActionEvent e) {
					saveAs();
				}});
		}
		return saveAsMenuItem;
	}
	
	/**
	 * This method initializes exitMenuItem	
	 * 	
	 * @return javax.swing.JMenuItem	
	 */
	private JMenuItem getExitMenuItem() {
		if (exitMenuItem == null) {
			exitMenuItem = new JMenuItem();
			exitMenuItem.setText("Exit");
			exitMenuItem.setAccelerator(KeyStroke.getKeyStroke('x'));
			exitMenuItem.setMnemonic(KeyEvent.VK_X);
			exitMenuItem.addActionListener(new ActionListener(){
				public void actionPerformed(ActionEvent e) {
					exit();
				}});
		}
		return exitMenuItem;
	}

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		// TODO load first argument?
		new SecurePropertiesDialog().setVisible(true);
	}

	/**
	 * This method initializes this
	 * 
	 * @return void
	 */
	private void initialize() {
		this.setSize(400, 300);
		this.setJMenuBar(getJJMenuBar());
		this.setTitle("Secure Properties Editor");
		this.setContentPane(getJContentPane());
		this.setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE);
	}

	/**
	 * This method initializes jContentPane
	 * 
	 * @return javax.swing.JPanel
	 */
	private JPanel getJContentPane() {
		if (jContentPane == null) {
			jContentPane = new JPanel();
			jContentPane.setLayout(new BorderLayout());
			jContentPane.add(getJScrollPane(), BorderLayout.CENTER);
			jContentPane.add(getJStatusBar(), BorderLayout.SOUTH);
		}
		return jContentPane;
	}

	private JLabel getJStatusBar() {
		if (this.statusBar==null) {
			this.statusBar = new JLabel();
		}
		return this.statusBar;
	}


	private void exit() {
		// TODO check dirty
		System.exit(0);
	}
	
	private void saveAs() {
		JFileChooser chooser = new JFileChooser();
		chooser.setMultiSelectionEnabled(false);
		if (JFileChooser.APPROVE_OPTION == chooser.showSaveDialog(this)) {
			this.currentFile =  chooser.getSelectedFile();
			save(this.currentFile);
		} else {
			status("Save cancelled by user");
		}
	}
	
	private void save() {
		if (this.currentFile==null) {
			saveAs();
		} else {
			save(this.currentFile);
		}
	}

	private void save(File file) {
		try {
			FileOutputStream os = new FileOutputStream(file);
			SecureProperties sp = new SecureProperties();
			// TODO key support
			sp.putAll(getTableMap());
			sp.store(os, "generated by Swing Editor");
			os.close();
			
			status("saved "+file);
		} catch (Exception e) {
			e.printStackTrace();
			status(e.toString());
		}
		
	}


	private Map<String, String> getTableMap() {
		int rowCount = this.dataModel.getRowCount();
		Hashtable<String, String> ret = new Hashtable<String, String>(rowCount);
		for (int i=0;i<rowCount;i++) {
			ret.put((String)this.dataModel.getValueAt(i, 0), (String)this.dataModel.getValueAt(i, 1));
		}
		return ret;
	}

	private void open() {
		JFileChooser chooser = new JFileChooser();
		chooser.setMultiSelectionEnabled(false);
		if (JFileChooser.APPROVE_OPTION == chooser.showOpenDialog(this)) {
			this.currentFile = chooser.getSelectedFile();
			String key = promptForKey();
			open(this.currentFile, key);
		} else {
			status("Open cancelled by user");
		}
	}


	private String promptForKey() {
		
		// TODO Auto-generated method stub
		return null;
	}


	private void status(String string) {
		// TODO send to status bar
		System.out.println(string);
		this.statusBar.setText(string);
	}


	private void open(File file, String key) {
		try {
			FileInputStream is = new FileInputStream(file);
			SecureProperties sp = new SecureProperties();
			if (key!=null) {
				sp.setKey(key);
			}
			sp.load(is);
			refreshTable(sp);
			status("loaded "+file);
		} catch (Exception e) {
			e.printStackTrace();
			status("Error opening file: "+e);
		}
	}


	private void refreshTable(SecureProperties sp) {
		while(dataModel.getRowCount()>0) {
			dataModel.removeRow(0);
		}
		for (Iterator it = sp.keySet().iterator() ; it.hasNext() ; ) {
			String k = (String) it.next();
			String v = sp.getProperty(k);
			dataModel.addRow(new String[]{k, v});
		}
		dataModel.fireTableRowsInserted(0, dataModel.getRowCount());
	}
	
	private void addNewRow() {
		dataModel.addRow(new String[]{"key", "value"});
		dataModel.fireTableRowsInserted(0, dataModel.getRowCount());
	}

}
